using BootstrapBlazorApp.Server.LLMs.api;
using BootstrapBlazorApp.Server.LLMs.chain;
using Newtonsoft.Json;
using System.ComponentModel;
using System.Reflection;

namespace BootstrapBlazorApp.Server.LLMs.parser;

public class JsonDicOutPutParser(Type type) : IBaseOutPutParser
{
    private string _json = string.Empty;
    private int _times;

    private static Dictionary<string, string> Parser(ChainContext input)
    {
        try
        {
            string jsonContent = input.GetLastMessage().Content;
            return JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonContent) ??
                   throw new InvalidOperationException();
        }
        catch (InvalidOperationException e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    public  Task<ChainContext> InvokeAsync(ChainContext input)
    {
        input.OutPutContent= Parser(input);
        input.PromptInputValue = Parser(input);
        return Task.FromResult(input);
    }

    public async IAsyncEnumerable<ChainContext> InvokeStreamAsync(ChainContext input)
    {
        _json += input.GetLastMessage().Content;
        if (!_json.Contains('}')||_times != 0)
        {
            yield break;
        }
        input.OutPutContent = Parser(input);
        input.PromptInputValue = Parser(input);
        yield return await Task.FromResult(input);
        _times++;
    }

    public string GetInstruction()
    {
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var descriptions = new Dictionary<string, string>();
        var instance = Activator.CreateInstance(type);
        foreach (var prop in properties)
        {
            var descriptionAttribute = prop.GetCustomAttribute<DescriptionAttribute>();
            if (descriptionAttribute != null)
            {
                descriptions[prop.Name] = descriptionAttribute.Description;
            }
        }

        string result = string.Join(", ", descriptions.Select(d => $"{d.Key}: {d.Value}"));
        string schema = JsonConvert.SerializeObject(instance, Formatting.Indented);
        return $"\n请你返回如下格式的Json,{schema},注意带上大括号，各个字段的描述为：{result},除了json之外不要返回其他内容";
    }
}
